package com.ls.mysql.quartz.service;

import com.ls.mysql.quartz.entity.Quartz;
import com.ls.mysql.quartz.entity.ScheduleJob;
import com.ls.mysql.quartz.scheduleTask.MyTask1;
import com.ls.mysql.quartz.scheduleTask.MyTask2;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;

/**
 * @Author Maple.Chen
 * @Description 动态任务调度控制器
 * 配合Controller的CRUD（Create、Retrieve、Update、Delete）动态对任务进行调度
 * @Date 16:19 2020/5/28
 **/
@Service
public class SchedulerServiceImpl implements SchedulerService {

    @Autowired
    private Scheduler scheduler;

    /*
    添加任务
     */
    @Override
    public String createJob(Quartz quartz) throws SchedulerException, ClassNotFoundException {

        if (!CronExpression.isValidExpression(quartz.getCronExpression())) {
            return "Illegal cron expression";   //表达式格式不正确
        }
        JobDetail jobDetail = null;
        //构建job信息
        if ("JobOne".equals(quartz.getJobGroup())) {
            jobDetail = JobBuilder.newJob(MyTask1.class).withIdentity(quartz.getJobName(), quartz.getJobGroup()).build();
        }
        if ("JobTwo".equals(quartz.getJobGroup())) {
            jobDetail = JobBuilder.newJob(MyTask2.class).withIdentity(quartz.getJobName(), quartz.getJobGroup()).build();
        } else {
            // 通过反射将任务类加入任务调度器
            Class clazz = Class.forName(quartz.getClassPath());
            System.out.println(clazz.getClass());
            jobDetail = JobBuilder.newJob(clazz).withIdentity(quartz.getJobName(), quartz.getJobGroup()).build();
        }

        //表达式调度构建器(即任务执行的时间,不立即执行)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartz.getCronExpression()).withMisfireHandlingInstructionDoNothing();

        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(quartz.getJobName(), quartz.getJobGroup()).startAt(quartz.getStartTime())
                .withSchedule(scheduleBuilder).build();

        //传递参数
        if (quartz.getDeliverParam() != null && !"".equals(quartz.getDeliverParam())) {
            trigger.getJobDataMap().put("invokeParam", quartz.getDeliverParam());
        }
        scheduler.scheduleJob(jobDetail, trigger);
        return "success";

    }

    /*
    删除任务
     */
    @Override
    public String deleteJob(String jobName, String jobGroup) throws SchedulerException {
        JobKey jobKey = new JobKey(jobName, jobGroup);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if (jobDetail == null) {
            return "jobDetail is null";
        } else if (!scheduler.checkExists(jobKey)) {
            return "jobKey is not exists";
        } else {
            scheduler.deleteJob(jobKey);
            return "success";
        }
    }

    /*
    暂停任务
     */
    @Override
    public boolean pauseJob(String jobName, String jobGroup) throws SchedulerException {
        JobKey jobKey = new JobKey(jobName, jobGroup);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if (jobDetail == null) {
            return false;
        } else {
            scheduler.pauseJob(jobKey);
            return true;
        }
    }

    /*
    恢复所有任务
     */
    @Override
    public void resumeAllJob() throws SchedulerException {
        scheduler.resumeAll();
    }

    /*
    查询任务状态
     */
    @Override
    public String retrieveJobState(String jobName, String jobGroup) throws SchedulerException {
        TriggerKey triggerKey = new TriggerKey(jobName, jobGroup);
        return scheduler.getTriggerState(triggerKey).name();
    }

    /*
    停止所有任务
     */
    @Override
    public void stopAllJob() throws SchedulerException {
        scheduler.pauseAll();
        return;
    }

    /*
    恢复某个任务
     */
    @Override
    public boolean resumeJob(String jobName, String jobGroup) throws SchedulerException {
        JobKey jobKey = new JobKey(jobName, jobGroup);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        if (jobDetail != null) {
            scheduler.resumeJob(jobKey);
            return true;
        }
        return false;
    }

    /*
    修改某个任务
     */
    @Override
    public String updateJob(Quartz quartz) throws SchedulerException {

        if (!CronExpression.isValidExpression(quartz.getCronExpression())) {
            return "Illegal cron expression";
        }
        TriggerKey triggerKey = TriggerKey.triggerKey(quartz.getJobName(), quartz.getJobGroup());
        JobKey jobKey = new JobKey(quartz.getJobName(), quartz.getJobGroup());
        if (scheduler.checkExists(jobKey) && scheduler.checkExists(triggerKey)) {
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            //表达式调度构建器,不立即执行
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartz.getCronExpression()).withMisfireHandlingInstructionDoNothing();
            //按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                    .withSchedule(scheduleBuilder).build();
            //修改参数
            if (!trigger.getJobDataMap().get("invokeParam").equals(quartz.getDeliverParam())) {
                trigger.getJobDataMap().put("invokeParam", quartz.getDeliverParam());
            }
            //按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
            return "success";
        } else {
            return "job or trigger not exists";
        }
    }

    /*
    查询任务列表中的所有任务
     */
    @Override
    public List<ScheduleJob> getAllJob() throws SchedulerException {
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
        Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
        List<ScheduleJob> jobList = null;
        if (jobKeys.size() > 0) {
            jobList = new ArrayList<>();
            for (JobKey jobKey : jobKeys) {
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
                    ScheduleJob job = new ScheduleJob();
                    job.setJobName(jobKey.getName());
                    job.setJobGroup(jobKey.getGroup());
                    job.setDescription("触发器:" + trigger.getKey());
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    job.setStatus(triggerState.name());
                    Class<? extends Job> jobClass = scheduler.getJobDetail(jobKey).getJobClass();
                    job.setJobClassPath(jobClass.toString());
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        TimeZone timeZone = cronTrigger.getTimeZone();
                        job.setTimeZone(timeZone.getID());
                        job.setCronExpression(cronExpression);
                    }
                    jobList.add(job);
                }
            }
        }
        return jobList;
    }

}
